Imports System.Reflection
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.GamerServices
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Input
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input.Touch
Imports System.IO

Public Class Guard
	Inherits Sprite

	''' <summary>
	''' Constructors a new player.
	''' </summary>
	Public Sub New(room As RoomNew, position As Vector2, GraphicsDevice__1 As GraphicsDevice, spriteEffect As SpriteEffects)
		graphicsDevice = GraphicsDevice__1
		spriteRoom = room
		LoadContent()


		'TAKE PLAYER Position
		Reset(position, spriteEffect)
	End Sub

	''' Loads the player sprite sheet and sounds.
	''' </summary>
	''' <note>i will add a parameter read form app.config</note>
	''' 
	''' 
	Private Sub LoadContent()

		spriteSequence = New List(Of Sequence)()
		Dim ax As New System.Xml.Serialization.XmlSerializer(spriteSequence.[GetType]())

		Dim txtReader As Stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(PrinceOfPersiaGame.CONFIG_PATH_CONTENT & PrinceOfPersiaGame.CONFIG_PATH_SEQUENCES & "GUARD_sequence.xml")


		'TextReader txtReader = File.OpenText(PrinceOfPersiaGame.CONFIG_PATH_CONTENT + PrinceOfPersiaGame.CONFIG_PATH_SEQUENCES + "KID_sequence.xml");
		'Stream astream = this.GetType().Assembly.GetManifestResourceStream("PrinceOfPersia.resources.KID_sequence.xml");
		spriteSequence = DirectCast(ax.Deserialize(txtReader), List(Of Sequence))

		For Each s As Sequence In spriteSequence
			s.Initialize(SpriteRoom.content)
		Next

		' Calculate bounds within texture size.         
		'faccio un rettangolo che sia largo la metà del frame e che parta dal centro
		Dim top As Integer = 0
		'StandAnimation.FrameHeight - height - 128;
		Dim left As Integer = 0
		'PLAYER_L_PENETRATION; //THE LEFT BORDER!!!! 19
		Dim width As Integer = 114
		'(int)(StandAnimation.FrameWidth);  //lo divido per trovare punto centrale *2)
		Dim height As Integer = 114
		'(int)(StandAnimation.FrameHeight);

		localBounds = New Rectangle(left, top, width, height)

		' Load sounds.            
		'killedSound = _room.content.Load<SoundEffect>("Sounds/PlayerKilled");
		'jumpSound = _room.content.Load<SoundEffect>("Sounds/PlayerJump");
		'fallSound = _room.content.Load<SoundEffect>("Sounds/PlayerFall");
	End Sub

	''' <summary>
	''' Handles input, performs physics, and animates the player sprite.
	''' </summary>
	''' <remarks>
	''' We pass in all of the input states so that our game is only polling the hardware
	''' once per frame. We also pass the game's orientation because when using the accelerometer,
	''' we need to reverse our motion when the orientation is in the LandscapeRight orientation.
	''' </remarks>
	Public Sub Update(gameTime As GameTime, keyboardState As KeyboardState, gamePadState As GamePadState, touchState As TouchCollection, accelState As AccelerometerState, orientation As DisplayOrientation)


		Dim elapsed As Single = CSng(gameTime.ElapsedGameTime.TotalSeconds)
		' TODO: Add your game logic here.
		sprite.UpdateFrame(elapsed, _position, flip, spriteState)

		If IsAlive = False Then
			DropDead()
			Return
		End If


		'bool thereIsKid = false;
		For Each s As Sprite In SpriteRoom.SpritesInRoom()
			Select Case s.[GetType]().Name
				Case "Player"
					If True Then
						If s.IsAlive = False Then
							Exit Select
						End If

						'thereIsKid = true;
						If s.Position.CheckOnRow(Position) Then
							If s.Position.CheckOnRowDistancePixel(Position) >= 0 And s.Position.CheckOnRowDistancePixel(Position) <= 70 And Alert = True And spriteState.Value().state = Enumeration.State.strike Then
								If spriteState.Value().Name = Enumeration.State.strike.ToString().ToUpper() Then
									'check if block
									If s.spriteState.Value().Name <> Enumeration.State.readyblock.ToString().ToUpper() Then
										spriteState.Value().Name = String.Empty
										s.Splash(True, gameTime)
										'Splash splash = new Splash(SpriteRoom, Position.Value, graphicsDevice, SpriteEffects.None, true);
										'Maze.sprites.Add(splash);

										s.Energy = s.Energy - 1
										s.StrikeRetreat()
									Else
										System.Console.WriteLine("P->" & Enumeration.State.readyblock.ToString().ToUpper())
										'blocked
									End If
								End If
								If s.Energy = 0 Then
									Fastheathe()

								End If
							End If

							Alert = True

							'Chenge Flip player..
							If Position.X < s.Position.X Then
								flip = SpriteEffects.None
							Else
								flip = SpriteEffects.FlipHorizontally
							End If







							Advance(s.Position, flip)
						Else
							Alert = False
						End If
						Exit Select
					End If
				Case Else
					Exit Select

			End Select
		Next



		If Alert = False Then
			Stand()
		End If
		'Ready();
		'else
		'  Stand();
	End Sub

	''' <summary>
	''' Draws the animated player.
	''' </summary>
	Public Sub Draw(gameTime As GameTime, spriteBatch As SpriteBatch)
		sprite.DrawSprite(gameTime, spriteBatch, _position.Value, flip, 0.5F)
	End Sub

	''' <summary>
	''' Resets the player to life.
	''' </summary>
	''' <param name="position">The position to come to life at.</param>
	Public Sub Reset(position As Vector2, spriteEffect As SpriteEffects)
		_position = New Position(New Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height), New Vector2(Player.SPRITE_SIZE_X, Player.SPRITE_SIZE_Y))
		_position.X = position.X
		_position.Y = position.Y
		Velocity = Vector2.Zero
		Energy = PrinceOfPersiaGame.CONFIG_KID_START_ENERGY

		flip = spriteEffect

		spriteState.Clear()

		Stand()

	End Sub

	Public Sub Stand()
		Stand(Enumeration.PriorityState.Normal, Nothing)
	End Sub

	Public Sub Stand(stoppable As Boolean)
		Stand(Enumeration.PriorityState.Normal, stoppable)
	End Sub

	Public Sub Stand(priority As Enumeration.PriorityState)
		Stand(priority, Nothing)
	End Sub

	Public Sub Stand(priority As Enumeration.PriorityState, stoppable As System.Nullable(Of Boolean))
		If priority = Enumeration.PriorityState.Normal And sprite.IsStoppable = stoppable Then
			Return
		End If

		spriteState.Add(Enumeration.State.stand, priority)
		sprite.PlayAnimation(spriteSequence, spriteState.Value())
	End Sub


	'?? the original guard engarde is used?
	Public Sub Engarde()
		Engarde(Enumeration.PriorityState.Normal, Nothing)
	End Sub
	Public Sub Engarde(priority As Enumeration.PriorityState, stoppable As System.Nullable(Of Boolean))
		If priority = Enumeration.PriorityState.Normal And sprite.IsStoppable = stoppable Then
			Return
		End If

		spriteState.Add(Enumeration.State.engarde, priority)
		sprite.PlayAnimation(spriteSequence, spriteState.Value())

	End Sub


	Public Sub GuardEngarde()
		GuardEngarde(Enumeration.PriorityState.Normal, Nothing)
	End Sub
	Public Sub GuardEngarde(priority As Enumeration.PriorityState, stoppable As System.Nullable(Of Boolean))
		If priority = Enumeration.PriorityState.Normal And sprite.IsStoppable = stoppable Then
			Return
		End If

		spriteState.Add(Enumeration.State.guardengarde, priority)
		sprite.PlayAnimation(spriteSequence, spriteState.Value())

	End Sub

	Public Sub Ready()
		Ready(Enumeration.PriorityState.Normal, Nothing)
	End Sub
	Public Sub Ready(priority As Enumeration.PriorityState, stoppable As System.Nullable(Of Boolean))
		If priority = Enumeration.PriorityState.Normal And sprite.IsStoppable = stoppable Then
			Return
		End If

		spriteState.Add(Enumeration.State.ready, priority)
		sprite.PlayAnimation(spriteSequence, spriteState.Value())

	End Sub

	Public Sub Advance(position__1 As Position, flip As SpriteEffects)
		If flip = SpriteEffects.FlipHorizontally Then
			Me.flip = SpriteEffects.None
		Else
			Me.flip = SpriteEffects.FlipHorizontally
		End If


        If position__1.X + SPRITE_SIZE_X - 30 <= Position.X Then
            'flip = SpriteEffects.None;
            spriteState.Add(Enumeration.State.advance, Enumeration.PriorityState.Normal)
        ElseIf position__1.X - SPRITE_SIZE_X + 30 >= Position.X Then
            spriteState.Add(Enumeration.State.advance, Enumeration.PriorityState.Normal)
        Else
            'flip = SpriteEffects.FlipHorizontally;
            Strike()
            'spriteState.Add(Enumeration.State.ready, Enumeration.PriorityState.Normal);
            Return
        End If

		sprite.PlayAnimation(spriteSequence, spriteState.Value())

	End Sub


	Public Sub HandleCollisionsNew()
		isGround()



		Dim playerBounds As Rectangle = _position.Bounding
		'Find how many tiles are near on the left
		Dim v4 As Vector4 = SpriteRoom.getBoundTiles(playerBounds)

		' For each potentially colliding Tile, warning the for check only the player row ground..W
		For y As Integer = CInt(Math.Truncate(v4.Z)) To CInt(Math.Truncate(v4.W))
			For x As Integer = CInt(Math.Truncate(v4.X)) To CInt(Math.Truncate(v4.Y))
				Dim tileBounds As Rectangle = SpriteRoom.GetBounds(x, y)
				Dim depth As Vector2 = RectangleExtensions.GetIntersectionDepth(playerBounds, tileBounds)
				Dim tileCollision As Enumeration.TileCollision = SpriteRoom.GetCollision(x, y)
				Dim tileType As Enumeration.TileType = SpriteRoom.[GetType](x, y)

				Select Case tileType
					Case Enumeration.TileType.spikes
						If IsAlive = False Then
							DirectCast(SpriteRoom.GetTile(x, y), Spikes).Open()
							Return
						End If

						If flip = SpriteEffects.FlipHorizontally Then
							If depth.X < 10 And depth.Y >= Player.SPRITE_SIZE_Y Then
								DirectCast(SpriteRoom.GetTile(x, y), Spikes).Open()

								' if (depth.X <= -30 & depth.Y >= Player.SPRITE_SIZE_Y & ((Spikes)SpriteRoom.GetTile(x, y)).State == Enumeration.StateTile.open)
								'   Impale();
							End If
						Else
							If depth.X > -10 And depth.Y >= Player.SPRITE_SIZE_Y Then
								DirectCast(SpriteRoom.GetTile(x, y), Spikes).Open()

								'if (depth.X >= 60 & depth.Y >= Player.SPRITE_SIZE_Y & ((Spikes)SpriteRoom.GetTile(x, y)).State == Enumeration.StateTile.open)
								'  Impale();
							End If
						End If

						Exit Select

					Case Enumeration.TileType.loose
						If flip = SpriteEffects.FlipHorizontally Then
							If depth.X < (-Tile.PERSPECTIVE - PLAYER_R_PENETRATION) Then
								DirectCast(SpriteRoom.GetTile(x, y), Loose).Press()
								'else
								'isLoosable();
							End If
						Else
							If depth.X > (Tile.PERSPECTIVE + PLAYER_L_PENETRATION) Then
								'45
								DirectCast(SpriteRoom.GetTile(x, y), Loose).Press()
								'else
								'isLoosable();
							End If
						End If
						Exit Select

					Case Enumeration.TileType.pressplate
						DirectCast(SpriteRoom.GetTile(x, y), PressPlate).Press()
						Exit Select
					Case Enumeration.TileType.gate, Enumeration.TileType.block
						If tileType = Enumeration.TileType.gate Then
							If DirectCast(SpriteRoom.GetTile(x, y), Gate).State = Enumeration.StateTile.opened Then
								Exit Select
							End If
						End If
						'if player are raised then not collide..


						'if sx wall i will penetrate..for perspective design
						If flip = SpriteEffects.FlipHorizontally Then
							'only for x pixel 
							If depth.X < (-Tile.PERSPECTIVE - PLAYER_R_PENETRATION) Then
								If spriteState.Value().state <> Enumeration.State.freefall And spriteState.Value().state <> Enumeration.State.highjump And spriteState.Value().state <> Enumeration.State.hang And spriteState.Value().state <> Enumeration.State.hangstraight And spriteState.Value().state <> Enumeration.State.hangdrop And spriteState.Value().state <> Enumeration.State.hangfall And spriteState.Value().state <> Enumeration.State.jumphangMed And spriteState.Value().state <> Enumeration.State.jumphangLong And spriteState.Value().state <> Enumeration.State.climbup And spriteState.Value().state <> Enumeration.State.climbdown Then
										'if (sprite.sequence.raised == false)
										'    Bump(Enumeration.PriorityState.Force);
										'else
										'    RJumpFall(Enumeration.PriorityState.Force);
										'return;
									_position.Value = New Vector2(_position.X + (depth.X - (-Tile.PERSPECTIVE - PLAYER_R_PENETRATION)), _position.Y)
								End If
							Else
								If sprite.sequence.raised = True Then
									_position.Value = New Vector2(_position.X, _position.Y)
								Else
									_position.Value = New Vector2(_position.X, _position.Y)
								End If
							End If
						Else
							If depth.X > (Tile.PERSPECTIVE + PLAYER_L_PENETRATION) Then
								'45
								'if(sprite.sequence.raised == false)
								If spriteState.Value().state <> Enumeration.State.freefall And spriteState.Value().state <> Enumeration.State.highjump And spriteState.Value().state <> Enumeration.State.hang And spriteState.Value().state <> Enumeration.State.hangstraight And spriteState.Value().state <> Enumeration.State.hangdrop And spriteState.Value().state <> Enumeration.State.hangfall And spriteState.Value().state <> Enumeration.State.jumphangMed And spriteState.Value().state <> Enumeration.State.jumphangLong And spriteState.Value().state <> Enumeration.State.climbup And spriteState.Value().state <> Enumeration.State.climbdown Then

									_position.Value = New Vector2(_position.X + (depth.X - (Tile.PERSPECTIVE + PLAYER_L_PENETRATION)), _position.Y)
									'Bump(Enumeration.PriorityState.Force);
									Return
								End If
							ElseIf sprite.sequence.raised = True Then
								_position.Value = New Vector2(_position.X, _position.Y)
							Else
								_position.Value = New Vector2(_position.X, _position.Y)
							End If
						End If
						playerBounds = BoundingRectangle
						Exit Select

					'default:
					'    _position.Value = new Vector2(_position.X, tileBounds.Bottom);
					'    playerBounds = BoundingRectangle;
					'    break;

				End Select
			Next
		Next
		'???
		'previousBottom = playerBounds.Bottom;
		'check if out room
		If _position.Y > RoomNew.BOTTOM_LIMIT + 10 Then
			Dim room As RoomNew = Maze.DownRoom(SpriteRoom)
			SpriteRoom = room
			_position.Y = RoomNew.TOP_LIMIT + 27
			' Y=77
			'For calculate height fall from damage points calculations..


            PositionFall = New Vector2(Position.X, (Game1.CONFIG_SCREEN_HEIGHT - RoomNew.BOTTOM_LIMIT - PositionFall.Y))
		ElseIf _position.X >= RoomNew.RIGHT_LIMIT Then
			Dim room As RoomNew = Maze.RightRoom(SpriteRoom)
			SpriteRoom = room
			_position.X = RoomNew.LEFT_LIMIT + 10
		ElseIf _position.X <= RoomNew.LEFT_LIMIT Then
			Dim room As RoomNew = Maze.LeftRoom(SpriteRoom)
			SpriteRoom = room
			_position.X = RoomNew.RIGHT_LIMIT - 10
		ElseIf _position.Y < RoomNew.TOP_LIMIT - 10 Then
			Dim room As RoomNew = Maze.UpRoom(SpriteRoom)
			SpriteRoom = room
				'Y=270
			_position.Y = RoomNew.BOTTOM_LIMIT - 24
		End If

	End Sub


End Class
